package image

import (
	"bytes"
	"fmt"
	"gin-fileserver/pkg/file"
	"gin-fileserver/pkg/setting"
	"gin-fileserver/pkg/util"
	"gin-fileserver/thumnailer"
	"io"

	log "github.com/sirupsen/logrus"

	"mime/multipart"
	"os"
	"path"
	"strings"

	"github.com/gin-gonic/gin"
)

func getImageName(image *multipart.FileHeader) string {
	ext := GetImageType(image)
	content, _ := image.Open()
	defer content.Close()
	data, _ := io.ReadAll(content)
	return util.EncodeMD5(data) + "." + ext
}

// 图片保存路径，thumb为是否为缩略图
func getSavePath(thumb bool) string {
	if thumb {
		return path.Join(setting.Cfg.FileServerSetting.StoragePath, setting.Cfg.FileServerSetting.ThumbnailImageFolderName)
	} else {
		return path.Join(setting.Cfg.FileServerSetting.StoragePath, setting.Cfg.FileServerSetting.OriginImageFolderName)
	}
}

// 运行时路径
func getRuntimePath() string {
	return setting.Cfg.AppSetting.RuntimePath
}

// 图片在服务器的完整路径，
func GetFullPath(thumb bool) string {
	return path.Join(getRuntimePath(), getSavePath(thumb))
}

// 检查图片
func CheckImage(image *multipart.FileHeader) error {
	if !checkImageExt(image) {
		return fmt.Errorf("Check ext failed: %v", image.Filename)
	}
	if !checkImageSize(image) {
		return fmt.Errorf("Check image size failed: %v", image.Filename)
	}
	return nil
}

// 获取图片类型
func GetImageType(file *multipart.FileHeader) string {
	f, _ := file.Open()
	buff := make([]byte, 3)
	f.Read(buff)
	ext := ""
	switch {
	case bytes.Equal(buff, []byte{0xFF, 0xD8, 0xFF}): // ÿØÿ (JPG)
		ext = "jpg"

	case bytes.Equal(buff, []byte{0x89, 0x50, 0x4E}): // .PNG (PNG)
		ext = "png"

	case bytes.Equal(buff, []byte{0x47, 0x49, 0x46}): // GIF (GIF)
		ext = "gif"
	}
	return ext
}

// 检查图片扩展名
func checkImageExt(f *multipart.FileHeader) bool {
	ext := GetImageType(f)
	for _, allowExt := range setting.Cfg.FileServerSetting.ImageAllowExts {
		if strings.EqualFold(allowExt, ext) {
			return true
		}
	}
	return false
}

// 检查图片文件大小
func checkImageSize(f *multipart.FileHeader) bool {
	size := f.Size
	return int(size) <= setting.Cfg.FileServerSetting.ImageMaxSize<<20
}

// 检查是否存在该图片
func IsExistImage(image string, thumb bool) bool {
	return file.CheckExist(path.Join(GetFullPath(thumb), image))
}

// // 保存图片
func SaveImagesFromFromData(imgs []*multipart.FileHeader, c *gin.Context) ([]string, error) {
	var imageUrls = []string{}
	// 对每个图片进行处理
	for _, img := range imgs {
		imageName := getImageName(img)
		// 如果不存在图片就保存
		if !IsExistImage(imageName, false) {
			savePath := path.Join(GetFullPath(false), imageName)
			// 检查是否存在
			if err := c.SaveUploadedFile(img, savePath); err != nil {
				log.Errorf("save image error: %v", err)
				return imageUrls, err
			}
			// 交给协程处理
			thumnailer.AddTask(savePath, path.Join(GetFullPath(true), imageName))
		}
		imageUrls = append(imageUrls, imageName)
	}
	return imageUrls, nil
}

// 删除图片
func DeleteImageUrls(urls []string) error {
	var err error
	for _, url := range urls {
		if url == "" {
			continue
		}
		os.Remove(path.Join(GetFullPath(true), url))
		e := os.Remove(path.Join(GetFullPath(false), url))
		if e != nil {
			log.Errorln(e)
		}
	}
	return err
}
